home *** CD-ROM | disk | FTP | other *** search
/ Sound Fx / Sound Fx.iso / Software / UNZIPED / MPW181-5 / _SETUP.1 / bebox.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-19  |  10.7 KB  |  442 lines

  1. /* This is the BeBox version written by John Fehr.
  2.  
  3.    Due to the changes I've made, this probably doesn't work anymore.
  4.    But it should be straightforward to get this working again. 
  5.     
  6.     -- Jeff Tsay */
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <MediaKit.h>
  11. #include <KernelKit.h>
  12. #include <Application.h>
  13. #include <InterfaceKit.h>
  14.  
  15. #include "args.h"
  16.  
  17. #define READ_BUFFERS 20    
  18. BLocker lb[READ_BUFFERS];
  19. char buffers[READ_BUFFERS][4096];
  20.  
  21. long curwbuf=0;
  22. long currbuf=0;
  23. long bebox_ok=1;
  24.  
  25. DWORD maplay(MPEG_Args *);
  26.  
  27. int ProcessArgs(int argc,char *argv[],MPEG_Args *);
  28.  
  29. MPEG_Args ma;
  30.  
  31. class mpegApp : public BApplication
  32. {
  33. private:
  34. thread_id        mpeg_decode_thread;
  35. thread_id        audio_thread;
  36. long            processed_args;
  37. public:
  38.                 mpegApp();
  39.                 ~mpegApp();
  40. virtual void    ArgvReceived(int argc,char **argv);
  41. virtual void    ReadyToRun(void);
  42. };
  43.  
  44.  
  45.  
  46. long MPEG_Reader_Process(void *data)
  47. {
  48.     //long retval=(long)start_decode();
  49.     long retval=maplay(&ma);
  50.     bebox_ok=0;
  51.     lb[curwbuf].Unlock();
  52.     fprintf(stderr,"MPEG_Reader_Process: returning %d\n",retval);
  53.     return retval;
  54. }
  55.  
  56. long stalled=0;
  57. double maxtime=0.0;
  58. double mintime=1000000.0;
  59. double t=0.0;
  60.  
  61. bool stream_function(void *arg,char *buffer,long count)
  62. {
  63.     int tcurrbuf;
  64.     memcpy(buffer,buffers[currbuf],count);
  65.     tcurrbuf=currbuf+1;
  66.     tcurrbuf=(tcurrbuf==READ_BUFFERS)?0:tcurrbuf;
  67.     if (tcurrbuf==curwbuf) stalled++;
  68.     lb[tcurrbuf].Lock();
  69.     lb[currbuf].Unlock();
  70.     currbuf=tcurrbuf;
  71.     if ((!bebox_ok) && currbuf==curwbuf)
  72.         return FALSE;
  73.     return TRUE;
  74. }
  75.  
  76. long completion_function(void *arg,long error)
  77. {
  78.     fprintf(stderr,"completed\n");
  79.     return B_NO_ERROR;
  80. }
  81.  
  82. long Audio_Process(void *data)
  83. {
  84.     BAudioSubscriber *b=(BAudioSubscriber *)data;
  85.     fprintf(stderr,"Entering stream\n");
  86.     b->EnterStream(NULL,TRUE,NULL,stream_function,completion_function,FALSE);
  87.     fprintf(stderr,"Unlocking\n");
  88.     lb[currbuf].Unlock();
  89.     fprintf(stderr,"ReadyToRun::done!\n");
  90.     b->Unsubscribe();
  91.     bebox_ok=0;
  92.     fprintf(stderr,"quiting!\n");
  93.     be_app->PostMessage(B_QUIT_REQUESTED);
  94.     return B_NO_ERROR;
  95. }
  96.  
  97.  
  98. int Usage(char *pname)
  99. {
  100.     fprintf(stderr,"\nusage: %s [-v] [-s] [-l] [-r]"
  101.         "[-f ushort] filename\n"
  102.         "  filename   filename of a MPEG audio stream or - for stdin\n"
  103. #ifdef VERBOSE
  104.         "  -v         verbose mode\n"
  105. #endif
  106.         "  -s         write pcm samples to stdout\n"
  107.         "  -l         decode only the left channel\n"
  108.         "  -r         decode only the right channel\n"
  109. #ifdef VERBOSE
  110.         "  -c         check for filter range violations\n"
  111. #endif
  112.         "  -f ushort  use this scalefactor instead of the default value 32768\n\n"
  113.         "@(#) MPEG Audio Player maplay 1.2 "
  114.         "(BeOS DR8.2 version)\n"
  115.         "@(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)\n"
  116.         "@(#) Berlin University of Technology\n"
  117.         "@(#) Created: 6/23/94 14:12:46\n"
  118.         "@(#) This program is free software. See the GNU General Public License\n"
  119.         "@(#) in the file COPYING for more details.\n\n"
  120.         ,pname);
  121.     return 0;
  122.   }
  123.  
  124. int ProcessArgs(int argc,char *argv[],MPEG_Args *ma)
  125. {
  126.   int i;
  127.   if (argc < 2 || !strncmp (argv[1], "-h", 2))
  128.   {
  129.     return Usage(argv[0]);
  130.   }
  131.   // parse arguments:
  132.   for (i = 1; i < argc; ++i)
  133.     if (argv[i][0] == '-' && argv[i][1])
  134.       switch ((int)argv[i][1])
  135.       {
  136.     case 'v':
  137. #ifdef VERBOSE
  138.       verbose_mode = TRUE;
  139. #else
  140.       fprintf(stderr,"maplay: not compiled with VERBOSE.\n");
  141. #endif
  142.       break;
  143.     case 's':
  144.       ma->stdout_mode = TRUE;
  145.       break;
  146.     case 'l':
  147.       ma->which_channels = left;
  148.       break;
  149.     case 'r':
  150.       ma->which_channels = right;
  151.       break;
  152.     case 'c':
  153. #ifdef VERBOSE
  154.       ma->filter_check = TRUE;
  155. #else
  156.       fprintf(stderr,"maplay: not compiled with VERBOSE.\n");
  157. #endif
  158.       break;
  159.     case 'f':
  160.       if (++i == argc)
  161.       {
  162.         fprintf(stderr,"please specify a new scalefactor after the -f option!\n");
  163.         exit (1);
  164.       }
  165.       ma->use_own_scalefactor = TRUE;
  166.       sscanf (argv[i], "%f", &ma->scalefactor);
  167.       break;
  168.     default:
  169.       return Usage(argv[0]);
  170.       }
  171.     else if (!ma->filename[0])
  172.       strcpy(ma->filename,argv[i]);
  173.     else
  174.       return Usage(argv[0]);
  175.  
  176.   if (!ma->filename[0])
  177.     return Usage(argv[0]);
  178.   if (!(ma->use_speaker || ma->use_headphone || ma->use_line_out))
  179.     ma->use_speaker = TRUE;
  180.  
  181.   if (!strcmp (ma->filename, "-"))
  182.     ma->stream = new Ibitstream (0);        // read from stdin
  183.   else
  184.     ma->stream = new Ibitstream (ma->filename);        // read from file
  185.  
  186.   ma->MPEGheader = new Header;
  187.   if (!ma->MPEGheader->read_header (ma->stream, &ma->crc))
  188.   {
  189.     fprintf(stderr,"no header found!\n");
  190.     return 0;
  191.   }
  192.   return 1;
  193. }
  194.  
  195. DWORD maplay_setup (MPEG_Args *ma)
  196. {
  197.  
  198.     enum e_channels which_channels = ma->which_c;
  199.  
  200.     e_mode mode;
  201.     e_sample_frequency sample_frequency;
  202.  
  203.   // get info from header of first frame:
  204.   if ((mode = ma->MPEGheader->mode ()) == single_channel)
  205.     which_channels = left;
  206.   sample_frequency = ma->MPEGheader->sample_frequency ();
  207.  
  208.   // create filter(s):
  209.   if (ma->use_own_scalefactor)
  210.     ma->filter1 = new SynthesisFilter (0, ma->scalefactor);
  211.   else
  212.     ma->filter1 = new SynthesisFilter (0);
  213.   if (mode != single_channel && ma->which_channels == both)
  214.     if (ma->use_own_scalefactor)
  215.       ma->filter2 = new SynthesisFilter (1, ma->scalefactor);
  216.     else
  217.       ma->filter2 = new SynthesisFilter (1);
  218.  
  219.   // create buffer:
  220.   if (ma->stdout_mode)
  221.     if (mode == single_channel || which_channels != both)
  222.       ma->buffer = (Obuffer *)new FileObuffer (1);
  223.     else
  224.       ma->buffer = new FileObuffer (2);
  225.   else
  226.   {
  227.     if (mode == single_channel || which_channels != both)
  228.         ma->buffer = new BEOSObuffer (1,ma->MPEGheader);    // mono
  229.     else
  230.         ma->buffer = new BEOSObuffer (2,ma->MPEGheader);    // stereo
  231.   }
  232.  
  233. #ifdef VERBOSE
  234.   if (verbose_mode)
  235.   {
  236.     // print informations about the stream
  237.     char *name = strrchr (filename, '/');
  238.     if (name)
  239.       ++name;
  240.     else
  241.       name = filename;
  242.     fprintf(stderr,"%s is a layer %s %s MPEG audio stream with",
  243.         name,ma->MPEGheader->layer_string(),ma->MPEGheader->mode_string());
  244.     if (!ma->MPEGheader->checksums ())
  245.       fprintf(stderr,"out");
  246.     fprintf(stderr, " checksums.\nThe sample frequency is %s"
  247.         " at a bitrate of %s\nThis stream is ",
  248.         ma->MPEGheader->sample_frequency_string(),ma->MPEGheader->bitrate_string());
  249.     if (ma->MPEGheader->original ())
  250.       fprintf(stderr,"an original");
  251.     else
  252.       fprintf(stderr,"a copy");
  253.     fprintf(stderr," and is ");
  254.     if (!ma->MPEGheader->copyright ())
  255.       fprintf(stderr,"not ");
  256.     fprintf(stderr, "copyright protected.\n");
  257.   }
  258. #endif
  259.   return 1;
  260. }
  261.  
  262.  
  263.  
  264. void mpegApp::ArgvReceived(int argc,char **argv)
  265. {
  266.     fprintf(stderr,"ArgsReceived()\n");
  267.     if (!ProcessArgs(argc,argv,&ma))
  268.     {
  269.         processed_args=0;
  270.         be_app->PostMessage(new BMessage(B_QUIT_REQUESTED));
  271.         return;
  272.     }
  273.     printf("Running maplay_setup\n");
  274.     maplay_setup(&ma);
  275.   // old_main(argc,argv);
  276.     processed_args=1;
  277. }
  278.  
  279. void mpegApp::ReadyToRun(void)
  280. {
  281.     fprintf(stderr,"ReadyToRun(): processed_args=%d\n",processed_args);
  282.     BAudioSubscriber *b;
  283.     long thread_return;
  284.  
  285.     if (!processed_args)
  286.     {
  287.         fprintf(stderr,"Args not processed.\n");
  288.         bebox_ok=0;
  289.         return;
  290.     }
  291.     // lock buffer[0] for the file reader (decoder) thread
  292.     lb[0].Lock();
  293.  
  294. printf("Creating mpeg_decode_thread\n");
  295.     if (resume_thread(
  296.         mpeg_decode_thread=spawn_thread(MPEG_Reader_Process,
  297.             "READ Task",B_URGENT_DISPLAY_PRIORITY,/*B_NORMAL_PRIORITY,*/NULL))<B_NO_ERROR)
  298.     {
  299.         fprintf(stderr,"Failed to spawn or resume DecodeProcess.\n");
  300.         bebox_ok=0;
  301.         return;
  302.     }
  303.     
  304.     // lock buffer 0 for the write task
  305.     lb[0].Lock();
  306.  
  307. //    snooze(3*1000000);
  308.  
  309.     fprintf(stderr,"spawned 'READ Task'\n");
  310.     // once the first buffer is read, lb[0] gets unlocked, so lock it for
  311.     if (!(b=new BAudioSubscriber("MPEG Audio Out")))
  312.     {
  313.         fprintf(stderr,"Error creating BAudioSubscriber.\n");
  314.         bebox_ok=0;
  315.         lb[currbuf].Unlock();
  316.         wait_for_thread(mpeg_decode_thread,&thread_return);
  317.         exit(0);
  318.     }
  319.     b->EnableDevice(B_DAC_OUT,TRUE);
  320.     b->SetVolume(B_DAC_OUT,1.0,1.0);
  321.     b->SetDACSampleInfo(2,2,B_BIG_ENDIAN,B_LINEAR_SAMPLES);
  322.     b->SetSamplingRate(44100);
  323.     if (b->Subscribe(B_DAC_STREAM,B_SHARED_SUBSCRIBER_ID,FALSE)!=B_NO_ERROR)
  324.     {
  325.         fprintf(stderr,"Error subscribing to B_DAC_STREAM as B_SHARED_SUBSCRIBER_ID.\n");
  326.         delete b;
  327.         bebox_ok=0;
  328.         lb[currbuf].Unlock();
  329.         wait_for_thread(mpeg_decode_thread,&thread_return);
  330.         exit(0);
  331.     }
  332.     if (resume_thread(
  333.         audio_thread=spawn_thread(Audio_Process,
  334.             "Audio Task",B_NORMAL_PRIORITY,(void *)b))<B_NO_ERROR)
  335.     {
  336.         fprintf(stderr,"Failed to spawn or resume Audio_Process.\n");
  337.         bebox_ok=0;
  338.         return;
  339.     }
  340. }
  341.  
  342. class mpegWindow : public BWindow
  343. {
  344. public:
  345.                 mpegWindow(BRect frame,char *title,window_type type,ulong flags);
  346. virtual    bool    QuitRequested();
  347. };
  348.  
  349. bool mpegWindow::QuitRequested()
  350. {
  351.     be_app->PostMessage(new BMessage(B_QUIT_REQUESTED));
  352.     return TRUE;
  353. }
  354.  
  355. mpegWindow::mpegWindow(BRect frame,char *title,window_type type,ulong flags)
  356.     : BWindow(frame,title,type,flags)
  357. {
  358. }
  359.  
  360. mpegApp::mpegApp(): BApplication('mpga') 
  361. {
  362.     mpeg_decode_thread=0;
  363.     audio_thread=0;
  364.     curwbuf=0;
  365.     currbuf=0;
  366.     bebox_ok=1;
  367.     processed_args=0;
  368.     
  369.     fprintf(stderr,"mpegApp()\n");
  370.     
  371.     mpegWindow *bw=new mpegWindow(BRect(91,102,230,140), "mpeg",
  372.         B_TITLED_WINDOW,B_NOT_RESIZABLE);
  373.     BButton *bb=new BButton(BRect(25,9,112,20),"Stop","Stop",
  374.         new BMessage(B_QUIT_REQUESTED),B_FOLLOW_NONE,B_WILL_DRAW);
  375.     bw->AddChild(bb);
  376.     bw->Show();
  377.  
  378. }
  379.  
  380. mpegApp::~mpegApp()
  381. {
  382.     long thread_return;
  383.     bebox_ok=0;
  384.     printf("set ok to 0\n");
  385.     if (mpeg_decode_thread) wait_for_thread(mpeg_decode_thread,&thread_return);
  386.     if (audio_thread) wait_for_thread(audio_thread,&thread_return);
  387.     printf("Thread returned\n");
  388. //    printf("Deleted\n");
  389. }
  390.  
  391.  
  392. static long c=0;
  393.  
  394. long curbpos=0;
  395.  
  396. long write_to_buffer(char *buf,int length)
  397. {
  398.     char *buffer=buffers[curwbuf];
  399.     long tcurwbuf;
  400.     long retlen=length;
  401.     
  402.     //printf("write %d, curbpos=%d,curwbuf=%d,currbuf=%d\n",length,curbpos,curwbuf,currbuf);
  403.     // fill in as many full buffers as we can
  404.     while (curbpos+length>=4096)
  405.     {
  406.         memcpy(buffer+curbpos,buf,4096-curbpos);
  407.         length-=(4096-curbpos);
  408.         buf+=(4096-curbpos);
  409.         curbpos=0;
  410.         
  411.         // release the hounds!  er.. the buffer
  412.         tcurwbuf=curwbuf+1;
  413.         tcurwbuf=(tcurwbuf==READ_BUFFERS)?0:tcurwbuf;
  414.         lb[tcurwbuf].Lock();
  415.         lb[curwbuf].Unlock();
  416.         curwbuf=tcurwbuf;
  417.         
  418.         // find the next output buffer.
  419.         buffer=buffers[curwbuf];
  420.     }
  421.     
  422.     // put what's left in the buffer
  423.     memcpy(buffer+curbpos,buf,length);
  424.     curbpos+=length;
  425. //    printf("curbpos=%d,length=%d\n",curbpos,length);
  426.  
  427.     return retlen;
  428. }
  429.  
  430. main(int argc,char *argv[])
  431. {
  432.     if (argc==1) 
  433.     {
  434.         return Usage(argv[0]);
  435.     }
  436.     mpegApp *ma=new mpegApp();
  437.     ma->Run();
  438.     delete ma;
  439.     fprintf(stderr,"stalled=%d\n",stalled);
  440.     return 0;
  441. }
  442.